unit untProxy;


interface

uses
  Windows,Sysutils,IdStack, IdIOHandler,IdIOHandlerSocket;



 function  CreateIDTCPConnection(FIOHandler:TIdIOHandler;UserName,Password:String;
                              AHost:String;APort:WORD) : Bool;


implementation



function  CreateIDTCPConnection(FIOHandler:TIdIOHandler;UserName,Password:String;
                              AHost:String;APort:WORD) : Bool;
var
  len, pos: Integer;
  tempBuffer: array [0..255] of Byte;
  ReqestedAuthMethod,
  ServerAuthMethod: Byte;
  tempPort: Word;
begin
  // defined in rfc 1928
  tempBuffer[2] := $0;   // No authentication

  ReqestedAuthMethod := tempBuffer[2];
  tempBuffer[0] := $5;     // socks version
  tempBuffer[1] := $1;     // number of possible authentication methods

  len := 2 + tempBuffer[1];
  FIOHandler.Send(tempBuffer, len);
  try
    FIOHandler.Recv(tempBuffer, 2); // Socks server sends the selected authentication method
  except
    Result := false;
    Exit;
  end;

  ServerAuthMethod := tempBuffer[1];
  if (ServerAuthMethod <> ReqestedAuthMethod) or (ServerAuthMethod = $FF) then begin
    Result := false;
    Exit;
  end;

  // Authentication process


  // Connection process
  tempBuffer[0] := $5;   // socks version
  tempBuffer[1] := $1;   // connect method
  tempBuffer[2] := $0;   // reserved
  // for now we stick with domain name, must ask Chad how to detect
  // address type
  tempBuffer[3] := $3;   // address type: IP V4 address: X'01'    {Do not Localize}
                         //               DOMAINNAME:    X'03'    {Do not Localize}
                         //               IP V6 address: X'04'    {Do not Localize}
  // host name
  tempBuffer[4] := Length(AHost);
  pos := 5;
  if Length(AHost) > 0 then begin
    Move(AHost[1], tempBuffer[pos], Length(AHost));
  end;
  pos := pos + Length(AHost);
  // port
  tempPort := GStack.WSHToNs(APort);
  Move(tempPort, tempBuffer[pos], SizeOf(tempPort));
  pos := pos + 2;

  FIOHandler.Send(tempBuffer, pos); // send the connection packet
  try
    FIOHandler.Recv(tempBuffer, 5);    // Socks server replies on connect, this is the first part
  except
    Result := false;
    Exit;
  end;

  if tempBuffer[1]=0 then
    Result := true// success, do nothing
  else
    Result := false;

  // type of destination address is domain name
  case tempBuffer[3] of
    // IP V4
    1: len := 4 + 2; // 4 is for address and 2 is for port length
    // FQDN
    3: len := tempBuffer[4] + 2; // 2 is for port length
    // IP V6
    4: len := 16 + 2; // 16 is for address and 2 is for port length
  end;

  try
    // Socks server replies on connect, this is the seconf part
    FIOHandler.Recv(tempBuffer[5], len-1);
  except
    Result := false;
  end;

end;


end.
